package com.example.yx1.demo32;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.*;
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.stream.Collectors;

@Configuration
public class WebConfig_1 {
    @Bean
    public TomcatServletWebServerFactory servletWebServerFactory() {return new TomcatServletWebServerFactory();}

    @Bean
    public DispatcherServlet dispatcherServlet() {return new DispatcherServlet();}

    @Bean
    public DispatcherServletRegistrationBean servletRegistrationBean(DispatcherServlet dispatcherServlet) {
        return new DispatcherServletRegistrationBean(dispatcherServlet,"/");
    }
    @Component
    //自己实现自定义的路径映射
    static class MyHandlerMapping implements HandlerMapping {
        //自动注入，以便能取到容器中的Bean
        @Autowired
        private ApplicationContext applicationContext;

        //提取成成员变量，方便后续使用
        private Map<String, Controller> beans;
        //初始化方法
        @PostConstruct
        public void init() {
            beans = applicationContext.getBeansOfType(Controller.class);
            beans.entrySet()
                    .stream()
                    .filter(e -> e.getKey().startsWith("/"))
                    .collect(Collectors.toMap(e->e.getKey(),e->e.getValue()));
            //测试是否能能得到
            System.out.println(beans);
        }

        @Override
        public boolean usesPathPatterns() {
            return false;
        }

        //做路径映射
        @Override
        public HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
            String key = request.getRequestURI();
            Controller controller = beans.get(key);
            if (controller == null) {
                return null;
            }
            //包装成链是因为可能需要过滤器啥的
            return new HandlerExecutionChain(controller);
        }
    }

    @Component
    //自己实现的方法调用
    static class MyHandlerAdapter implements HandlerAdapter {

        //限定只能匹配Controller类型的Bean
        @Override
        public boolean supports(Object handler) {
            return handler instanceof Controller;
        }

        @Override
        public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            if (handler instanceof Controller) {
                Controller controller = new Controller() {
                    @Override
                    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
                        return null;
                    }
                };
                //进行处理
                controller.handleRequest(request,response);
            }

            return null;
        }

        @Override
        public long getLastModified(HttpServletRequest request, Object handler) {
            return -1;
        }
    }

    @Component("/c1")
    public static class Controller1 implements Controller {
        @Override
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            response.getWriter().print("this is c1");
            return null;
        }
    }

    @Component("c2")
    public static class Controller2 implements Controller{
        @Override
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            response.getWriter().print("this is c2");
            return null;
        }
    }

    @Bean("/c3")
    public Controller controller3(){
        return (request, response) -> {
            response.getWriter().print("this is c3");
            return null;
        };
    }
}
